﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Soft.Service
{

    /// <summary>
    /// 服务基类
    /// </summary>
    public abstract  class BaseService:ErrorResponse,IDisposable,IServerControl
    {

        /// <summary>
        /// 服务名称
        /// </summary>
        private readonly string mServiceName;


        /// <summary>
        ///服务是否被终结 
        /// </summary>
        private bool mTerminated = true;


        /// <summary>
        /// 服务是否被释放
        /// </summary>
        private bool mDisposed;


        /// <summary>
        /// 日志文件对象
        /// </summary>
        private LogFile mLogFile;


        /// <summary>
        /// 错误信息的集合
        /// </summary>
        private InformationCollection mInformations = new InformationCollection();


        /// <summary>
        /// 基本服务类  服务名称，日志服务名称
        /// </summary>
        /// <param name="serviceName">服务名称</param>
        /// <param name="logFileName">日志文件名称</param>
        public BaseService(string serviceName, string logFileName)
        {
            if (string.IsNullOrWhiteSpace(serviceName))
            {
                serviceName = base.GetType().Name;
            }
            this.mServiceName = serviceName;
            if (string.IsNullOrWhiteSpace(logFileName))
            {
                logFileName = base.GetType().Name;
            }
            this.mLogFile = new LogFile(logFileName, TimeUnit.Day, 100, "Log", Encoding.Unicode);
        }


        ~BaseService()
        {
            try
            {
                this.Dispose();
            }
            catch
            {
            }
        }

     
        /// <summary>
        /// 最大的信息数量
        /// </summary>
        public int MaxInformationCount { get; set; } = 100;


        /// <summary>
        /// 服务启动
        /// </summary>
        /// <returns></returns>
        public Result Start()
        {
            Result result = new Result();
            if (this.State == ServerState.Stopped)
            {
                this.WriteLog("".PadRight(80, '-'), true);
                this.WriteLog("Starting '" + this.mServiceName + "' service......", true);
                this.State = ServerState.Starting;
                try
                {
                    this.mTerminated = false;
                    result.ReceiveResult(this.OnStart());
                    this.WriteLog("The service '" + this.mServiceName + "' has been started.", true);
                }
                catch (Exception ex)
                {
                    string text = ex.ToString();
                    result.AddError(text, null);
                    this.WriteLog(text, true);
                    this.WriteLog("The start service '" + this.mServiceName + "' failed!", true);
                }
                this.State = (result.Succeed ? ServerState.Started : ServerState.Error);
                this.mTerminated = (this.State != ServerState.Started);
            }
            return result;
        }


        /// <summary>
        /// 服务启动时的操作
        /// </summary>
        /// <returns></returns>
        protected abstract Result OnStart();


        /// <summary>
        /// 服务停止
        /// </summary>
        public void Stop()
        {
            if (this.State == ServerState.Started)
            {
                this.State = ServerState.Stopping;
                this.mTerminated = true;
                this.WriteLog("Stopping service '" + this.mServiceName + "'......", true);
                this.OnStop();
                this.WriteLog("Service stopped.", true);
                this.State = ServerState.Stopped;
            }
        }


       /// <summary>
       /// 服务停止时的操作
       /// </summary>
        protected abstract void OnStop();


        /// <summary>
        /// 服务时候被终结了
        /// </summary>
        public bool Terminated
        {
            get
            {
                return this.mTerminated;
            }
            set
            {
                if (value && this.mTerminated != value)
                {
                    this.Stop();
                }
            }
        }


        /// <summary>
        /// 服务的名称
        /// </summary>
        public string ServiceName
        {
            get
            {
                return this.mServiceName;
            }
        }


        /// <summary>
        /// 服务的状态
        /// </summary>
        public ServerState State { get; protected set; } = ServerState.Stopped;


        /// <summary>
        /// 服务的释放
        /// </summary>
        public void Dispose()
        {
            if (!this.mDisposed)
            {
                this.OnDispose();
                this.mDisposed = true;
            }
        }


        /// <summary>
        /// 服务睡眠时间
        /// </summary>
        /// <param name="secondsTimeout"></param>
        /// <param name="exitLogic"></param>
        protected void Sleep(int secondsTimeout, ExitLogic exitLogic)
        {
            int num = 0;
            while (!this.Terminated && (exitLogic == null || !exitLogic()))
            {
                Thread.Sleep(1000);
                num++;
                if (num >= secondsTimeout)
                {
                    break;
                }
            }
        }


        /// <summary>
        /// 服务销毁时的操作
        /// </summary>
        protected virtual void OnDispose()
        {
            this.Stop();
        }


        /// <summary>
        /// 错误处理
        /// </summary>
        /// <param name="error"></param>
        protected override void OnError(Information error)
        {
            if (this.MaxInformationCount > 0)
            {
                if (this.mInformations.Count >= this.MaxInformationCount)
                {
                    this.mInformations.RemoveAt(0);
                }
                this.mInformations.Add(error);
            }
            this.mLogFile.Write(error.ToString(), true, WriteFileMode.RealTime);
            base.OnError(error);
        }


        /// <summary>
        /// 写入日志
        /// </summary>
        /// <param name="text"></param>
        /// <param name="includeDateTime"></param>
        protected void WriteLog(string text, bool includeDateTime = true)
        {
            if (includeDateTime)
            {
                this.mLogFile.Write(text, true, WriteFileMode.Default);
                return;
            }
            this.mLogFile.Write(text, WriteFileMode.Default);
        }


        /// <summary>
        /// 添加错误处理程序
        /// </summary>
        /// <param name="value"></param>
        public  void  AddError(ErrorEventHandle value)
        {
            base.Error += value;
        }


        /// <summary>
        /// 移除错误处理程序
        /// </summary>
        /// <param name="value"></param>
        public void RemoveError(ErrorEventHandle value)
        {
            base.Error -= value;
        }


    }
}
